#pragma once

#include <windows.h>
#include <ctime>
#include <set>
#include <vector>
#include <limits>
#include <cassert>
#include <random>
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glut.h>
#include "cuda.h"
#include "cutil_inline.h"

#define _SCANF_
//#define _COMMAND_LINE_
//#define _FILTE_NEAR_POINT_
//#define DEBUG_FUCK
//#ifdef _KERNEL_INFO_
#define _DELETE_IT_

#define TOLERANCE (0.5*FLT_EPSILON)
#define M_PI 3.1415926535897932f
#define PAGE_SIZE 4096
#define SITES_SIZE 1024
#define VERTEX_POOL_SIZE 1024
#define EDGE_POOL_SIZE VERTEX_POOL_SIZE
#define WXN_EPSILON (FLT_EPSILON )
#define EVENT_HEAP_SIZE SITES_SIZE
#define ARC_HEAP_SIZE VERTEX_POOL_SIZE
#define ARC_POOL_SIZE ( VERTEX_POOL_SIZE * 2 )
#define ACTIVE_EDGE_POOL_SIZE ( ARC_POOL_SIZE )


#ifndef _DELETE_IT_
#define cutilSafeCall(x) (x)
#define cuPrintf printf
#define cudaMemcpyDeviceToHost 1
#define cudaMemcpyHostToDevice 2
#define cudaHostAllocDefault 1


void cudaMalloc(void** p , int _size){
	*p = malloc(_size);
}

void cudaHostAlloc(void** p,int _size,int unused){
	*p = malloc(_size);
}

void cudaFree(void * p)
{
	free(p);
}


void cudaMemcpy(void* p1,void* p2,int _size,int unused){
	memcpy(p1,p2,_size);
}
struct float2{
	float x , y;
};
float2 make_float2(float x,float y){
	float2 tmp;
	tmp.x = x;tmp.y = y;
	return tmp;
}
struct int2{
	int x , y;
};
int2 make_int2(int x,int y){
	int2 tmp;
	tmp.x = x;tmp.y = y;
	return tmp;
}
#endif

const int argcNum = 8;
float2 MinPoint;
float2 MaxPoint;
bool displayOutsideFlag = false;
int sleepTime;

float picDrawLength = 200; 
float2 picCorner1 = make_float2(10,10);
float2 picCorner2 = make_float2(10+picDrawLength,10+picDrawLength);
float totalLength = 1;
float totalHalf = totalLength / 2;



float calcDistance( const float2 &p1 , const float2 &p2 )
{
	return sqrt( (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y) );
}

bool inBox(const float2& p , const float2& box1 , const float2& box2)//box1 is downleft point,box2 is upright point
{
	return p.x > box1.x && p.x < box2.x && p.y > box1.y && p.y < box2.y;
}
float det(const float& x1,const float& y1,const float& x2,const float& y2){
	return x1 * y2 - x2 * y1;
}

float cross(const float2 &a,const float2 &b,const float2 &c){
	return det(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);
}

bool segcross(const float2 &a , const float2 &b , const float2 &c,const float2 &d,float2 &p)
{
	float s1,s2,s3,s4;
	s1 = cross(a,b,c);
	s2 = cross(a,b,d);
	s3 = cross(c,d,a);
	s4 = cross(c,d,b);
	if( s1 * s2 < 0 && s3 * s4 < 0 ){
		p.x = (c.x * s2 - d.x * s1 ) / ( s2 - s1 );
		p.y = (c.y * s2 - d.y * s1 ) / ( s2 - s1 );
		return true;
	}else{
		return false;
	}
} 
float2 intersectSegBox(const float2& p1 , const float2& p2 , const float2& box1 ,const float2& box2 )
{
	float2 resultPoint;
	float2 b1 = make_float2(box1.x , box1.y);
	float2 b2 = make_float2(box2.x , box1.y);
	float2 b3 = make_float2(box2.x , box2.y);
	float2 b4 = make_float2(box1.x , box2.y);
	if( segcross(p1 , p2 , b1 , b2 , resultPoint) ) return resultPoint;
	if( segcross(p1 , p2 , b2 , b3 , resultPoint) ) return resultPoint;
	if( segcross(p1 , p2 , b3 , b4 , resultPoint) ) return resultPoint;
	if( segcross(p1 , p2 , b4 , b1 , resultPoint) ) return resultPoint;
}


bool getIntersectDisplay(float2& p1,float2& p2,float2 box1,float2 box2){
	bool p1Inbox = inBox(p1,box1,box2);
	bool p2Inbox = inBox(p2,box1,box2);
	if( !p1Inbox && !p2Inbox ){
		return false;
	}else if( !p1Inbox && p2Inbox ){
		p1 = intersectSegBox( p1 , p2 , box1 , box2 );
		//printf("p1.x %f p1.y %f\n",p1.x , p1.y);
	}else if( p1Inbox && !p2Inbox ){
		p2 = intersectSegBox( p1 , p2 , box1 , box2 );
		//printf("p2.x %f p2.y %f\n" , p2.x , p2.y);
	}

	return true;
}

